home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fritz: All Fritz
/
All Fritz.zip
/
All Fritz
/
FILES
/
PROGBLER
/
WASM211B.LZH
/
IO.ASM
< prev
next >
Wrap
Assembly Source File
|
1987-11-20
|
48KB
|
1,862 lines
List-
;=============================================================================
; Basic I/O Procedures
;
; These routines provide methods to manipulate strings and processes simple
; I/O. The procedures are completely MS/PC DOS compatible, the hardware or
; BIOS is never directly accessed (except for SOUND_SPK_P).
;
; All parameters are passed on the stack unless specified otherwise. All
; string addresses consist of a segment and offset (they are 32-bit). The
; offset should always be pushed on the stack first. If more than one string
; address is required, the destination string (the string to be modified)
; should be pushed on the stack first. Note that data may be returned on the
; stack as specified and should be removed by the programmer before, for
; instance, returning from a routine. Parameters will be returned even if an
; error occurs, though the data may not be valid.
;
; If a new string is created (for instance the time string), it will exist in
; a local buffer and the address that is returned on the stack will point to
; that buffer. Local buffers should never be written to, only read from.
;
; All registers are preserved (unless they are used to pass parameters). The
; flags are not explicitly preserved. Note particularly that the direction
; flag (DF) may be cleared. If an error is detected, the carry flag will be
; set and generally the operation will not be carried out.
;
; Strings are defined as any sequence of 0 to 255 characters preceded by a
; length byte, except for file names, which must be a sequence of characters
; terminated by a byte 00. These two string types are not interchangeable, the
; only routines that require the latter type are the routines that open,
; create, or delete files (OPEN_FIL_P, CREATE_FIL_P, and DELETE_FIL_P).
;
; The stack is used extensively and should have about 200 bytes free before
; pushing any parameters and calling the routines.
;
; String manipulation:
;
; CLEAR_STR_P clear a string
; TRUNCATE_STR_P truncate a string
; COPY_STR_P copy a string from one location to another
; APPEND_STR_P append a string to another
; APPEND_CHRS_P append characters to a string
; FORMAT_RGT_P append a string to another after formatting
; JUSTIFY_RGT_P append a string to another right justified
; LOWER_CHR_P make a character lower-case
; UPPER_CHR_P make a character upper-case
; MAKE_BIN_P translate a string to a binary number
; MAKE_DEC_P translate a binary number to a string
; DAY_STR_P get the string representing the day
; MONTH_STR_P get the string representing the month
; TIME_STR_P get the string representing the time
; MAKE_NAM_P translate a string into the file name format
; MAKE_STR_P translate a file string into normal format
;
; Keyboard:
;
; INPUT_STA_P return input status
; INPUT_CHR_P input a character
; INPUT_HID_P input a character without screen echo
; INPUT_STR_P input a string
;
; Display:
;
; HOME_CUR_P move the cursor home (1)
; LEFT_CUR_P move the cursor left (1)
; RIGHT_CUR_P move the cursor right (1)
; UP_CUR_P move the cursor up (1)
; DOWN_CUR_P move the cursor down (1)
; SAVE_CUR_P save the cursor position (1)
; RESTORE_CUR_P restore the cursor position (1)
; LOCATE_CUR_P move the cursor to a location (1)
; NORMAL_ATR_P change the attribute to normal (1)
; BOLD_ATR_P change the attribute to bold (1)
; UNDERLINE_ATR_P change the attribute to underline (1)
; BLINK_ATR_P change the attribute to blinking (1)
; REVERSE_ATR_P change the attribute to reverse video (1)
; CLEAR_SCR_P clear the screen and home the cursor (1)
; DISPLAY_CHR_P display a character
; LINE_P start a new display line
; DISPLAY_STR_P display a string
; DISPLAY_LIN_P display a string and start a new line
;
; Speaker:
;
; SOUND_BEL_P beep the speaker
; SOUND_SPK_P sound the speaker at freq. for duration (2)
;
; File:
;
; OPEN_FIL_P open a file
; CREATE_FIL_P create or truncate a file
; DELETE_FIL_P delete a file
; READ_FIL_P read from a file
; WRITE_FIL_P write to a file
; SEEK_FIL_P move a file read write pointer
; SIZE_FIL_P get the size of a file
; CLOSE_FIL_P close a file
; FREE_DSK_P return free disk space
;
; (1) Requires that ANSI.SYS or compatible device driver be installed.
; (2) Hardware specific, duration is dependent on a 4.77 MHz computer.
;================================================
; This creates a library header so this file can
; read by the dispatcher code in DISPATCH.ASM.
; The next two source lines vary depending
; whether or not the file is being included into
; the source file directly, or is being
; assembled separately as a runtime library.
;presently set up to be included directly
If 0 ;set to 1 if external library,
;0 if included directly
;Include 'E:Library.Asm' ;add this line (remove semi-colon) if external
;library, remove line (turn it into comment
;by adding semi-colon) if included directly
Dw Offset Clear_Str_P
Dw Offset Truncate_Str_P
Dw Offset Copy_Str_P
Dw Offset Append_Str_P
Dw Offset Append_Chrs_P
Dw Offset Format_Rgt_P
Dw Offset Justify_Rgt_P
Dw Offset Lower_Chr_P
Dw Offset Upper_Chr_P
Dw Offset Make_Bin_P
Dw Offset Make_Dec_P
Dw Offset Day_Str_P
Dw Offset Month_Str_P
Dw Offset Time_Str_P
Dw Offset Make_Nam_P
Dw Offset Make_Str_P
Dw Offset Input_Sta_P
Dw Offset Input_Chr_P
Dw Offset Input_Hid_P
Dw Offset Input_Str_P
Dw Offset Home_Cur_P
Dw Offset Left_Cur_P
Dw Offset Right_Cur_P
Dw Offset Up_Cur_P
Dw Offset Down_Cur_P
Dw Offset Locate_Cur_P
Dw Offset Normal_Atr_P
Dw Offset Bold_Atr_P
Dw Offset Underline_Atr_P
Dw Offset Blink_Atr_P
Dw Offset Reverse_Atr_P
Dw Offset Clear_Scr_P
Dw Offset Display_Chr_P
Dw Offset Sound_Bel_P
Dw Offset Line_P
Dw Offset Display_Str_P
Dw Offset Display_Lin_P
Dw Offset Open_Fil_P
Dw Offset Create_Fil_P
Dw Offset Delete_Fil_P
Dw Offset Read_Fil_P
Dw Offset Write_Fil_P
Dw Offset Seek_Fil_P
Dw Offset Size_Fil_P
Dw Offset Close_Fil_P
Dw Offset Free_Dsk_P
Dw Offset Sound_Spk_P
Dw Offset Save_Cur_P
Dw Offset Restore_Cur_P
Endif
;================================================
; Set the length of the destination string to
; zero. The string address is returned on the
; stack.
Clear_Str_P Proc Near
Push Si
Push Ds
Push Bp ;save registers
Mov Bp, Sp
Mov Si, [Bp+10] ;get source offset
Mov Ds, [Bp+8] ;get source segment
Mov Byte [Si], 0 ;zero length
Pop Bp
Pop Ds
Pop Si
Clc ;no error
Ret
Endp ;Clear_Str_P
;================================================
; Set the length of the destination string to
; the specifed length. The length must in the
; low byte of the last word pushed on the
; stack. The string address is returned on the
; stack and also the flags are set by a
; comparision of the new and previous lengths.
Truncate_Str_P Proc Near
Push Ax
Push Si
Push Ds
Push Bp ;save registers
Mov Bp, Sp
Mov Si, [Bp+14] ;get source offset
Mov Ds, [Bp+12] ;get source segment
Mov Al, [Bp+10] ;get new length
Mov Ah, Al
Xchg Al, [Si] ;set new length and get old
Cmp Al, Ah ;compare sizes, set flags
Pop Bp
Pop Ds
Pop Si
Pop Ax
Ret 2
Endp ;Truncate_Str_P
;================================================
; Copy the source string to the destination.
; The destination string address is returned on
; the stack.
Copy_Str_P Proc Near
Push Cx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Di, [Bp+20] ;get destination offset
Mov Es, [Bp+18] ;get destination segment
Mov Si, [Bp+16] ;get source offset
Mov Ds, [Bp+14] ;get source segment
Mov Cl, [Si] ;length
Sub Ch, Ch
Inc Cx ;include length byte
Rep
Movsb ;move string
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Cx ;restore registers
Clc ;no error
Ret 4
Endp ;Copy_Str_P
;================================================
; Append the source string to the destination
; string. The destination string address is
; returned on the stack. The carry is set if
; the string would be too long.
Append_Str_P Proc Near
Push Ax
Push Bx
Push Cx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Di, [Bp+24] ;get destination offset
Mov Es, [Bp+22] ;get destination segment
Mov Si, [Bp+20] ;get source offset
Mov Ds, [Bp+18] ;get source segment
Seg Es
Mov Al, [Di] ;destination length
Mov Cl, [Si] ;source length
Sub Ah, Ah
Mov Ch, Ah
Mov Bx, Ax
Add Al, Cl ;new total length
Jc AppendStrError ;jump if too big
Seg Es
Mov [Di], Al ;save new length
Add Di, Bx ;destination pointer to end
Inc Di ;don't forget length byte
Inc Si ;... and source
Rep
Movsb ;move string
Clc ;no error
AppendStrError
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret 4
Endp ;Append_Str_P
;================================================
; Append some number of characters to the
; destination string. The character to append
; must be in the high byte of the last word
; pushed on the stack and the byte count must
; be in the low byte. The string address is
; returned on the stack. The carry is set if
; the string would be too long.
Append_Chrs_P Proc Near
Push Ax
Push Bx
Push Cx
Push Di
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Di, [Bp+18] ;get destination offset
Mov Es, [Bp+16] ;get destination segment
Mov Cl, [Bp+14] ;get number of characters to append
Seg Es
Mov Al, [Di] ;destination length
Sub Ah, Ah
Mov Ch, Ah
Mov Bx, Ax
Add Al, Cl ;new total length
Jc AppendChrError ;jump if too big
Seg Es
Mov [Di], Al ;save new length
Add Di, Bx ;pointer to end
Inc Di ;length byte
Mov Al, [Bp+15] ;get character
Rep
Stosb ;store
Clc ;no error
AppendChrError
Pop Bp
Pop Es
Pop Di
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret 2
Endp ;Append_Chrs_P
;================================================
; Append a right justified source string to the
; destination string. Note that the source
; string is justified itself before it is
; appended. The character to use in justifing
; must be in the high byte of the last word
; pushed on the stack and the final source
; string size must be in the low byte. The
; destination string address is returned on the
; stack. The carry is set if the final string
; would be too long or could not be formatted.
Format_Rgt_P Proc Near
Push Ax
Push Bx
Push Cx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Di, [Bp+26] ;get destination offset
Mov Es, [Bp+24] ;get destination segment
Mov Si, [Bp+22] ;get source offset
Mov Ds, [Bp+20] ;get source segment
;--- add the justifing characters
Seg Es
Mov Al, [Di] ;destination length
Mov Bh, [Si] ;source length
Add Al, Bh ;length of two strings
Jc FormatRgtError ;jump if too big
Mov Bl, [Bp+18] ;get final source size
Sub Bl, Bh ;calculate amount of justify
Jc FormatRgtError ;jump if too small
Add Al, Bl ;final total length
Jc FormatRgtError ;jump if too big
Mov Bh, [Bp+19] ;get character to justify with
Push Di
Push Es
Push Bx
Call Append_Chrs_P ;append characters
Add Sp, 4 ;throw away address, not needed
;--- append the string
Seg Es
Mov Al, [Di] ;destination length
Mov Cl, [Si] ;source length
Sub Ah, Ah
Mov Ch, Ah ;clear high bytes of sizes
Mov Bx, Ax
Add Al, Cl ;new total length
Seg Es
Mov [Di], Al ;save new length
Add Di, Bx ;destination pointer to end
Inc Di ;don't forget length byte
Inc Si ;... and source
Rep
Movsb ;move string
Clc ;no error
FormatRgtError
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret 6
Endp ;Format_Rgt_P
;================================================
; Append the source string to the destination
; string right justified. The character to use
; in justifing must be in the high byte of the
; last word pushed on the stack and the final
; string size must be in the low byte. The
; destination string address is returned on the
; stack. The carry is set if the final string
; would be too long or could not be justified.
Justify_Rgt_P Proc Near
Push Ax
Push Bx
Push Cx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Di, [Bp+26] ;get destination offset
Mov Es, [Bp+24] ;get destination segment
Mov Si, [Bp+22] ;get source offset
Mov Ds, [Bp+20] ;get source segment
Seg Es
Mov Al, [Di] ;destination length
Mov Cl, [Si] ;source length
;--- add the justifing characters
Mov Bh, Al
Add Bh, Cl ;length of both strings in BL
Jc Badjustify ;jump if too big
Mov Bl, [Bp+18] ;get final size
Sub Bl, Bh ;calculate amount of justify
Jc Badjustify ;jump if final size too small
Mov Bh, [Bp+19] ;get character to justify with
Push Di
Push Es
Push Bx
Call Append_Chrs_P ;append characters
Add Sp, 4 ;throw away address, not needed
;--- append the string
Sub Ah, Ah
Mov Bh, Ah
Mov Ch, Bh ;clear high bytes of sizes
Add Ax, Bx ;add for new characters
Mov Bx, Ax
Add Al, Cl ;new total length
Seg Es
Mov [Di], Al ;save new length
Add Di, Bx ;destination pointer to end
Inc Di ;don't forget length byte
Inc Si ;... and source
Rep
Movsb ;move string
Clc ;no error
BadJustify
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret 6
Endp ;Justify_Rgt_P
;================================================
; Convert character in AL to lower-case. AL not
; preserved.
Lower_Chr_P Proc Near
Cmp Al, 'A' ;lower limit
Jb NotLowerChr
Cmp Al, 'Z' ;upper limit
Ja NotLowerChr
Add Al ,'a'-'A' ;make lower
NotLowerChr Ret
Endp ;Lower_Chr_P
;================================================
; Convert character in AL to upper-case. AL not
; preserved.
Upper_Chr_P Proc Near
Cmp Al, 'a' ;lower limit
Jb NotUpperChr
Cmp Al, 'z' ;upper limit
Ja NotUpperChr
Sub Al ,'a'-'A' ;make upper
NotUpperChr Ret
Endp ;Upper_Chr_P
;================================================
; Translate the destination string into a 32-
; bit number. The number is returned on the
; stack in place of the string address (the
; high 16 bits should be popped first). If
; there is an error the carry is set and a
; particular value is returned in the low word
; of the value: 0000 means the source was a nul
; string, 0001 means overflow, and 0002 means
; there was a bad character in the string.
Make_Bin_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Di
Push Si
Push Ds
Push Bp ;save registers
Cld ;clear direction
Mov Bp, Sp
Mov Si, [Bp+20] ;get source offset
Mov Ds, [Bp+18] ;get source segment
Cmp Byte [Si], 0 ;check if nul string
Je MakeBinNul ;jump if so
Mov Bx, 10 ;base ten
Lodsb ;load length
Mov Cl, Al
Sub Ch, Ch ;CX has length
Sub Dx, Dx
Mov Di, Dx ;expects value in DX.DI
Jmp MakeBinStart ;jump to start, skip value x 10
;--- loop for each digit
;--- multiply total times ten
MakeBinLoop
Mov Ax, [Bp+18] ;high word of value
Mul Ax, Bx ;multply, AX has high word result
Jc MakeBinOver ;jump if overflow
Mov Di, Ax ;save high word
Mov Ax, [Bp+20] ;low word of value
Mul Ax, Bx ;multiply, DX.AX has result
Add Dx, Di ;add high result
Jc MakeBinOver ;jump if overflow
Mov Di, Ax ;save low word, new value is in DX.DI
;--- add in next digit
MakeBinStart
Lodsb ;load next digit
Sub Al, '0' ;get value
Cmp Al, 9 ;check value
Ja MakeBinBad ;jump if illegal character
Sub Ah, Ah
Add Di, Ax ;add in new value
Jnc MakeBinNohi ;jump if no carry to high word
Inc Dx ;increment high word
Jz MakeBinOver ;jump if overflow
MakeBinNohi
Mov [Bp+20], Di ;save low word
Mov [Bp+18], Dx ;save high word
Loop MakeBinLoop ;loop back for next digit
;--- number successfully converted
Clc
MakeBinDone
Pop Bp
Pop Ds
Pop Si
Pop Di
Pop Dx
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret
;--- nul string
MakeBinNul
Mov Word [Bp+20], 0000 ;error code
Mov Word [Bp+18], 0000
Stc
Jmps MakeBinDone
;--- overflow
MakeBinOver
Mov Word [Bp+20], 0001 ;error code
Mov Word [Bp+18], 0000
Stc
Jmps MakeBinDone
;--- illegal character
MakeBinBad
Mov Word [Bp+20], 0002 ;error code
Mov Word [Bp+18], 0000
Stc
Jmps MakeBinDone
Endp ;Make_Bin_P
;================================================
; Translate the 32-bit number into a decimal
; ASCII string. The low word of the number
; must be pushed onto the stack first. The
; local string address is returned on the stack.
Make_Dec_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Cld ;clear direction
Mov Ax, Cs
Mov Ds, Ax
Mov Es, Ax ;set data segments
Mov Bx, 10 ;number base
Sub Cx, Cx ;CX counts digits
Mov Di, Offset MakeDecBuff ;number buffer location
Mov Si, Di
Inc Di
Mov Bp, Sp ;pointer to value
;--- loop for each digit, at least one 0
MakeDecLoop
Mov Ax, [Bp+20] ;high word of value
Sub Dx, Dx ;clear for divide
Div Ax, Bx ;divide, DX gets remainder
Mov [Bp+20], Ax ;save quotient (high word)
Mov Ax, [Bp+22] ;low word of value
Div Ax, Bx ;divide, DX gets remainder (the digit)
Mov [Bp+22], Ax ;save quotient (low word)
Add Dl, '0' ;make ASCII
Mov Al, Dl
Stosb ;store
Inc Cx ;another digit
Cmp Word [Bp+22], 0 ;check if low word zero
Jne MakeDecLoop ;jump if not
Cmp Word [Bp+20], 0 ;check if high word zero
Jne MakeDecLoop ;jump if not
;--- done with number
Mov [Si], Cl ;save length
Shr Cx ;CX/2
Jz MakeDecDone ;jump if nothing to switch
Dec Di ;last digit
Inc Si ;first digit
Xchg Si, Di ;SI points to end, DI points to beginning
;--- reverse digits
MakeDecRLoop
Seg Es
Mov Al, [Di] ;load front character
Xchg Al, [Si] ;swap with end character
Stosb ;store new front character
Dec Si ;back up
Loop MakeDecRLoop ;loop back for each digit
;--- finished
MakeDecDone
Mov Word [Bp+22], Offset MakeDecBuff ;save offset
Mov [Bp+20], Ds ;save segment
Clc
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Dx
Pop Cx
Pop Bx
Pop Ax ;restore registers
Ret
;--- data
MakeDecBuff Label Byte ;string buffer
Ds 11
Endp ;Make_Dec_P
;================================================
; Get the string representing the present day.
; The day index (Sunday=0, etc.) must be in the
; low byte of the word pushed on the stack. The
; local string address is returned on the
; stack.
Day_Str_P Proc Near
Sub Sp, 2 ;room for return data
Push Bx
Push Ds
Push Bp
Mov Bp, Sp
Mov Bx, [Bp+8]
Mov [Bp+6], Bx ;move return address
Mov Bx, Cs
Mov Ds, Bx ;load data segment
Mov Bl, [Bp+10] ;get day index
Sub Bh, Bh ;clear high part of index
Shl Bx ;times two (two bytes per entry)
Add Bx, Offset DayStrList ;offset of string location
Mov Bx, [Bx] ;get string location
Mov [Bp+10], Bx ;save offset
Mov [Bp+8], Ds ;save segment
Pop Bp
Pop Ds
Pop Bx
Ret
;--- table of day strings
DayStrList Label Word
Dw Offset DayStr01, Offset DayStr02, Offset DayStr03, Offset DayStr04
Dw Offset DayStr05, Offset DayStr06, Offset DayStr07
;--- day strings
DayStr01 Db 6,'Sunday'
DayStr02 Db 6,'Monday'
DayStr03 Db 7,'Tuesday'
DayStr04 Db 9,'Wednesday'
DayStr05 Db 8,'Thursday'
DayStr06 Db 6,'Friday'
DayStr07 Db 8,'Saturday'
Endp ;Day_Str_P
;================================================
; Get the string representing the present
; month. The month index (January=0, etc.) must
; be in the low byte of the word pushed on the
; stack. The local string address is returned
; on the stack.
Month_Str_P Proc Near
Sub Sp, 2 ;room for return data
Push Bx
Push Ds
Push Bp
Mov Bp, Sp
Mov Bx, [Bp+8]
Mov [Bp+6], Bx ;move return address
Mov Bx, Cs
Mov Ds, Bx ;load data segment
Mov Bl, [Bp+10] ;get day index
Sub Bh, Bh ;clear high part of index
Shl Bx ;times two (two bytes per entry)
Add Bx, Offset MonthStrList ;offset of string location
Mov Bx, [Bx] ;get string location
Mov [Bp+10], Bx ;save offset
Mov [Bp+8], Ds ;save segment
Pop Bp
Pop Ds
Pop Bx
Ret
;--- table of month strings
MonthStrList Label Word
Dw Offset MonthStr01, Offset MonthStr02, Offset MonthStr03
Dw Offset MonthStr04, Offset MonthStr05, Offset MonthStr06
Dw Offset MonthStr07, Offset MonthStr08, Offset MonthStr09
Dw Offset MonthStr10, Offset MonthStr11, Offset MonthStr12
;--- month strings
MonthStr01 Db 7,'January'
MonthStr02 Db 8,'February'
MonthStr03 Db 5,'March'
MonthStr04 Db 5,'April'
MonthStr05 Db 3,'May'
MonthStr06 Db 4,'June'
MonthStr07 Db 4,'July'
MonthStr08 Db 6,'August'
MonthStr09 Db 9,'September'
MonthStr10 Db 7,'October'
MonthStr11 Db 8,'November'
MonthStr12 Db 8,'December'
Endp ;Month_Str_P
;================================================
; Get the string representing the time the in
; XX:XX am/pm format (e.g. 3:27 pm). The hours
; must be in the high byte of the word on the
; stack and the minutes must be in the low
; byte. The local string address is returned on
; the stack.
Time_Str_P Proc Near
Sub Sp, 2 ;room for return data
Push Ax
Push Ds
Push Bp
Mov Bp, Sp
Mov Bx, [Bp+8]
Mov [Bp+6], Bx ;move return address
Mov Ax, Cs
Mov Ds, Ax ;set segment registers
Mov Ax, Offset TimeStrBuff ;storage
Push Ax
Push Ds
Call Clear_Str_P ;initialize string
;--- hours
Mov Al, [Bp+11] ;get hours
Or Al, Al ;check if 12am to 12:59am
Jnz TimeStrHour1 ;jump if not
Mov Al, 12 ;set to 12
TimeStrHour1
Cmp Al, 13 ;check if next half
Jb TimeStrHour2 ;jump if not
Sub Al, 12 ;reset half
TimeStrHour2
Sub Ah, Ah
Push Ax
Sub Ax, Ax ;high word of number is zero
Push Ax
Call Make_Dec_P ;create number string
Call Copy_Str_P ;copy string to buffer
Mov Ah, ':' ;colon
Mov Al, 1 ;count
Push Ax
Call Append_Chrs_P ;append character
;--- minutes
Mov Al,[Bp+10] ;get minutes
Sub Ah, Ah
Push Ax
Sub Ax, Ax ;high word of number is zero
Push Ax
Call Make_Dec_P ;create number string
Mov Al, 2 ;string size
Mov Ah, '0' ;justify character
Push Ax
Call Format_Rgt_P ;append string to buffer
;--- am/pm
Mov Ax, Offset TimeStrPm
Cmp Byte [Bp+11], 12 ;check after noon
Jae TimeStrAmPm ;jump if so
Mov Ax, Offset TimeStrAm
TimeStrAmPm
Push Ax
Push Ds
Call Append_Str_P ;append string
;--- set return data
Pop Ax ;return segment
Mov [Bp+8], Ax ;save
Pop Ax ;return offset
Mov [Bp+10], Ax ;save
Pop Bp
Pop Ds
Pop Ax
Ret
;--- data
TimeStrPm Db 3,' pm'
TimeStrAm Db 3,' am'
TimeStrBuff Label Byte
Db ?,'??:?? ??'
Endp ;Time_Str_P
;================================================
; Translate string format into a name format
; (a sequence of characters terminated by byte
; 00). The local string address is returned on
; the stack.
Make_Nam_P Proc Near
Push Cx
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Mov Bp, Sp
Mov Si, [Bp+16] ;get offset
Mov Ds, [Bp+14] ;get segment
Mov Cx, Cs
Mov Es, Cx ;set local data segment
Mov Di, Offset MakeNamBuff ;local buffer
Mov Cl, [Si] ;length
Sub Ch, Ch
Inc Si ;skip length
Rep
Movsb ;copy string
Seg Es
Mov Byte [Di], 0 ;store terminating zero
Mov Word [Bp+16], Offset MakeNamBuff ;save offset
Mov [Bp+14], Es ;save segment
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Cx
Clc
Ret
;--- local storage
MakeNamBuff Label Byte
Ds 256 ;room for 255 bytes and 00
Endp ;Make_Nam_P
;================================================
; Translate a name format string (a sequence of
; characters terminated by byte 00) into a normal
; string (a string of characters preceded by a byte
; containing its length). The local string address
; is returned on the stack.
Make_Str_P Proc Near
Push Ax
Push Di
Push Si
Push Ds
Push Es
Push Bp ;save registers
Mov Bp, Sp
Mov Si, [Bp+16] ;get offset
Mov Ds, [Bp+14] ;get segment
Mov Ax, Cs
Mov Es, Ax ;set local data segment
Mov Di, Offset MakeStrBuff+1 ;local buffer, skip length byte
Sub Ah, Ah ;initial byte count
;--- loop for each byte
MakeStrLoop
Lodsb ;load next byte
Or Al, Al ;check if end of string
Jz MakeStrFinish ;jump if so
Inc Ah ;update count
Jz MakeStrError ;jump if too big
Stosb ;store byte
Jmp MakeStrLoop ;loop back for next byte
;--- finished
MakeStrFinish
Clc
MakeStrDone
Mov Di, Offset MakeStrBuff ;local buffer
Seg Es
Mov [Di], Ah ;save string length
Mov [Bp+16], Di ;save offset
Mov [Bp+14], Es ;save segment
Pop Bp
Pop Es
Pop Ds
Pop Si
Pop Di
Pop Ax
Clc
Ret
;--- error, string too long
MakeStrError
Mov Ah, 255 ;max length
Stc
Jmps MakeStrDone
;--- local storage
MakeStrBuff Label Byte
Ds 256 ;room for 255 bytes and length
Endp ;Make_Str_P
;================================================
; Return the status of the standard input device.
; ZF=1 if no characters waiting.
Input_Sta_P Proc Near
Push Ax
Mov Ah, 0bh ;function number
Int 21h ;execute
Or Al, Al ;set ZF
Pop Ax
Ret
Endp ;Input_Sta_P
;================================================
; Input a character from the standard input. AL
; returns the character. AX not preserved.
Input_Chr_P Proc Near
Mov Ah, 1 ;function number
Int 21h ;execute
Ret
Endp ;Input_Chr_P
;================================================
; Input a character from the standard input
; without a screen echo. AL returns the
; character. AX not preserved.
Input_Hid_P Proc Near
Mov Ah, 8 ;function number
Int 21h ;execute
Ret
Endp ;Input_Hid_P
;================================================
; Input a string from the user and move the cursor
; to the next line. The maximum input size (0 to
; 254) must be in the low byte of a word pushed on
; the stack. If the input length is too big the
; carry is set, otherwise the carry is cleared and
; the ZF will be set if the input length is zero.
; The string address is returned.
Input_Str_P Proc Near
Sub Sp, 2 ;allow for extra word of data
Push Ax
Push Bx
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ax, Cs
Mov Ds, Ax ;set data segment
Mov Ax, [Bp+12]
Mov [Bp+10], Ax ;fix return address
Mov Al, [Bp+14] ;get max input length
Mov Word [Bp+14], Offset InputStrBuff+1 ;set offset
Mov Word [Bp+12], Ds ;set segment
Inc Al ;account for CR
Jz Badinput ;jump if too big (can only be up to 254)
Mov InputStrBuff, Al ;save length
Mov Ah, 0ah ;function
Mov Dx, Offset InputStrBuff ;formatted buffer
Int 21h ;execute
Mov Dl, 10 ;linefeed
Call Display_Chr_P ;display
Mov Bl, InputStrBuff + 1 ;get input length
Sub Bh, Bh ;clear upper byte
Mov Byte [Bx+InputStrBuff+2], 0 ;store 00 on CR
Or Bx, Bx ;set ZF
Clc
InputStrDone
Pop Bp
Pop Ds
Pop Dx
Pop Bx
Pop Ax
Ret
;--- input was too big
Badinput
Mov Byte InputStrBuff + 1, 0 ;set zero input length
Stc
Jmps InputStrDone
;--- data
InputStrBuff Label Byte
Db ? ;maximum length
Db ? ;input length
Ds 255 ;storage for full string
Endp ;Input_Str_P
;================================================
; Move the cursor to the upper left corner.
Home_Cur_P Proc Near
Push Ax
Mov Ax, Offset HomeCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
HomeCurCode Db 6,27,'[1;1H' ;control string
Endp ;Home_Cur_P
;================================================
; Move the cursor left one column.
Left_Cur_P Proc Near
Push Ax
Mov Ax, Offset LeftCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
LeftCurCode Db 3,27,'[D' ;control string
Endp ;Left_Cur_P
;================================================
; Move the cursor right one column.
Right_Cur_P Proc Near
Push Ax
Mov Ax, Offset RightCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
RightCurCode Db 3,27,'[C' ;control string
Endp ;Right_Cur_P
;================================================
; Move the cursor up one row.
Up_Cur_P Proc Near
Push Ax
Mov Ax, Offset UpCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
UpCurCode Db 3,27,'[A' ;control string
Endp ;Up_Cur_P
;================================================
; Move the cursor down one row.
Down_Cur_P Proc Near
Push Ax
Mov Ax, Offset DownCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
DownCurCode Db 3,27,'[B' ;control string
Endp ;Down_Cur_P
;================================================
; Save the cursor positon.
Save_Cur_P Proc Near
Push Ax
Mov Ax, Offset SaveCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
SaveCurCode Db 3,27,'[s' ;control string
Endp ;Save_Cur_P
;================================================
; Restore the cursor position.
Restore_Cur_P Proc Near
Push Ax
Mov Ax, Offset RestoreCurCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
RestoreCurCode Db 3,27,'[u' ;control string
Endp ;Restore_Cur_P
;================================================
; Move the cursor to a specified position. The
; column must be in the low byte of the word
; pushed on the stack and the row must be in
; the high byte. The upper left corner is 0,0.
; Will only calculate up to 99,99 (which should be
; large enough for most screens).
Locate_Cur_P Proc Near
Push Ax
Push Bx
Push Dx
Push Ds
Push Bp
Mov Ax, Cs
Mov Ds, Ax
Mov Bp, Sp
Mov Bx, Offset LocateCurCode
Mov Dl, 10 ;base number
Mov Dh, '0' ;ascii conversion value
Mov Al, [Bp+13] ;row
Sub Ah, Ah
Div Al, Dl ;get digits
Add Al, Dh
Add Ah, Dh ;make both ascii
Mov [Bx+3], Al ;store tens digit
Mov [Bx+4], Ah ;store ones digit
Mov Al, [Bp+12] ;column
Sub Ah, Ah
Div Al, Dl ;get digits
Add Al, Dh
Add Ah, Dh ;make both ascii
Mov [Bx+6], Al ;store tens digit
Mov [Bx+7], Ah ;store ones digit
Push Bx
Push Ds
Call Display_Str_P ;send string
Pop Bp
Pop Ds
Pop Dx
Pop Bx
Pop Ax
Ret 2
LocateCurCode Db 8,27,'[??;??H'
Endp ;Locate_Cur_P
;================================================
; Set display attribute to normal.
Normal_Atr_P Proc Near
Push Ax
Mov Ax, Offset NormalAtrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
NormalAtrCode Db 4,27,'[0m' ;control string
Endp ;Normal_Atr_P
;================================================
; Set display attribute to bold.
Bold_Atr_P Proc Near
Push Ax
Mov Ax, Offset BoldAtrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
BoldAtrCode Db 4,27,'[1m' ;control string
Endp ;Bold_Atr_P
;================================================
; Set display attribute to underline.
Underline_Atr_P Proc Near
Push Ax
Mov Ax, Offset UnderlineAtrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
UnderlineAtrCode Db 4,27,'[4m' ;control string
Endp ;Underline_Atr_P
;================================================
; Set display attribute to blink.
Blink_Atr_P Proc Near
Push Ax
Mov Ax, Offset BlinkAtrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
BlinkAtrCode Db 4,27,'[5m' ;control string
Endp ;Blink_Atr_P
;================================================
; Set display attribute to reverse video.
Reverse_Atr_P Proc Near
Push Ax
Mov Ax, Offset ReverseAtrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
ReverseAtrCode Db 4,27,'[7m' ;control string
Endp ;Reverse_Atr_P
;================================================
; Clear the screen and home the cursor.
Clear_Scr_P Proc Near
Push Ax
Mov Ax, Offset ClearScrCode
Push Ax
Push Cs
Call Display_Str_P ;send string
Pop Ax
Ret
ClearScrCode Db 4,27,'[2J' ;control string
Endp ;Clear_Scr_P
;================================================
; Display the character in DL to the standard
; output.
Display_Chr_P Proc Near
Push Ax
Mov Ah, 2 ;function number
Int 21h ;execute
Pop Ax
Ret
Endp ;Display_Chr_P
;================================================
; Sound the speaker.
Sound_Bel_P Proc Near
Push Dx
Mov Dl, 7 ;BEL
Call Display_Chr_P ;display
Pop Dx
Ret
Endp ;Sound_Bel_P
;================================================
; Start a new display line.
Line_P Proc Near
Push Dx
Mov Dl, 13 ;CR
Call Display_Chr_P ;display
Mov Dl, 10 ;LF
Call Display_Chr_P ;display
Pop Dx
Ret
Endp ;Line_P
;================================================
; Display the destination string to the
; standard output device.
Display_Str_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ah, 40h ;function number
Mov Bx, [Bp+16] ;get offset
Mov Ds, [Bp+14] ;get segment
Mov Cl, [Bx] ;get length byte
Sub Ch, Ch ;clear upper byte, CX=length
Mov Dx, Bx
Inc Dx ;start of string body
Mov Bx, 1 ;standard output
Int 21h ;execute
Pop Bp
Pop Ds
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret 4
Endp ;Display_Str_P
;================================================
; Display the destination string to the
; standard output device and then move the
; cursor to the next line.
Display_Lin_P Proc Near
Push Ax
Push Bp
Sub Sp, 4
Mov Bp, Sp
Mov Ax, [Bp+12]
Mov [Bp+2], Ax ;offset
Mov Ax, [Bp+10]
Mov [Bp], Ax ;segment
Call Display_Str_P ;display string
Call Line_P ;next line
Pop Bp
Pop Ax
Ret 4
Endp ;Display_Lin_P
;================================================
; Open a file for reading and writing. The name
; location must be on the stack. The file handle
; is returned on the stack. The name should be a
; byte 00 terminated string.
Open_Fil_P Proc Near
Push Ax
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Al, 00000010b ;read/write status
Mov Ah, 3dh ;function number
Mov Dx, [Bp+12] ;name offset
Mov Ds, [Bp+10] ;name segment
Int 21h ;execute
Mov [Bp+12], Ax ;save handle
Pop Bp
Pop Ds
Pop Dx
Pop Ax
Ret 2
Endp ;Open_Fil_P
;================================================
; Create or truncate a file for reading and
; writing. The name location must be on the stack.
; The file handle is returned on the stack. The
; name should be a byte 00 terminated string.
Create_Fil_P Proc Near
Push Ax
Push Cx
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ah, 3ch ;function number
Sub Cx, Cx ;normal attribute
Mov Dx, [Bp+14] ;name offset
Mov Ds, [Bp+12] ;name segment
Int 21h ;execute
Mov [Bp+14], Ax ;save handle
Pop Bp
Pop Ds
Pop Dx
Pop Cx
Pop Ax
Ret 2
Endp ;Create_Fil_P
;================================================
; Delete a file. The location of the name of the
; file must be passed on the stack. The name should
; be a byte 00 terminated string.
Delete_Fil_P Proc Near
Push Ax
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ah, 41h ;function number
Mov Dx, [Bp+12] ;name offset
Mov Ds, [Bp+10] ;name segment
Int 21h ;execute
Pop Bp
Pop Ds
Pop Dx
Pop Ax
Ret 4
Endp
;================================================
; Read from a file. The handle, bytes to read,
; and buffer address (32 bit) must be pushed on
; the stack. The handle and bytes read are returned.
Read_Fil_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ah, 3fh ;function number
Mov Bx, [Bp+20] ;handle
Mov Cx, [Bp+18] ;bytes to write
Mov Dx, [Bp+16] ;buffer offset
Mov Ds, [Bp+14] ;buffer segment
Int 21h ;execute
Mov [Bp+18], Ax ;save bytes written
Pop Bp
Pop Ds
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret 4
Endp ;Read_Fil_P
;================================================
; Write to a file. The handle, bytes to write,
; and buffer address (32 bit) must be pushed on
; the stack. The handle and bytes written are
; returned.
Write_Fil_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Ds
Push Bp
Mov Bp, Sp
Mov Ah, 40h ;function number
Mov Bx, [Bp+20] ;handle
Mov Cx, [Bp+18] ;bytes to write
Mov Dx, [Bp+16] ;buffer offset
Mov Ds, [Bp+14] ;buffer segment
Int 21h ;execute
Mov [Bp+18], Ax ;save bytes written
Pop Bp
Pop Ds
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret 4
Endp ;Write_Fil_P
;================================================
; Seek an absolute location within a file. The
; handle, a 16 bit record size, and a 32 bit (low
; word first) record number must be passed on the
; stack. The handle is returned. Does not check
; for too large a seek.
Seek_Fil_P Proc Near
Push Ax
Push Bx
Push Cx
Push Dx
Push Bp
Mov Bp, Sp
Mov Bx, [Bp+16] ;record size
Mov Ax, [Bp+12] ;high word
Mul Ax, Bx ;multiply high word (error if carry)
Mov Cx, Ax ;first part of high word
Mov Ax, [Bp+14] ;low word high word of record number
Mul Ax, Bx ;multiply low word
Add Cx, Dx ;add in second part of high word (error if carry)
Mov Dx, Ax ;final absolute offset in CX.DX
Mov Bx, [Bp+18] ;handle
Mov Ax, 4200h ;function number
Int 21h ;execute
Pop Bp
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret 6
Endp ;Seek_Fil_P
;================================================
; Return the size of a file and move the read/
; write pointer to the end of the file. The handle
; and the (32 bit) size are returned. The high
; word of the size must be popped first.
Size_Fil_P Proc Near
Sub Sp, 4
Push Ax
Push Bx
Push Cx
Push Dx
Push Bp
Mov Bp, Sp
Mov Ax, [Bp+14]
Mov [Bp+10], Ax ;fix return address
Mov Ax, 4202h ;function number
Mov Bx, [Bp+16] ;handle
Sub Cx, Cx
Mov Dx, Cx ;move to offset from end 0000.0000
Int 21h ;execute
Mov [Bp+14], Ax ;low word
Mov [Bp+12], Dx ;high word
Pop Bp
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret
Endp ;Size_Fil_P
;================================================
; Close a file. The file handle must be passed on
; the stack.
Close_Fil_P Proc Near
Push Ax
Push Bx
Push Bp
Mov Bp, Sp
Mov Ah, 3eh ;function number
Mov Bx, [Bp+8] ;get file handle
Int 21h ;execute
Pop Bp
Pop Bx
Pop Ax
Ret 2
Endp
;================================================
; Return the number of bytes free on the disk.
; The drive number (0=default, 1=A, etc.) must be
; in the low byte of a word passed on the stack.
; The 32 bit number containing the free bytes is
; returned. Carry set if invalid drive.
Free_Dsk_P Proc Near
Sub Sp, 2
Push Ax
Push Bx
Push Cx
Push Dx
Push Bp
Mov Bp, Sp
Mov Ax, [Bp+12]
Mov [Bp+10], Ax ;fix return address
Mov Ah, 36h ;function number
Mov Dl, [Bp+14] ;drive code
Int 21h ;execute
Cmp Ax, -1 ;check if error
Je FreeDskError ;jump if so
Mul Ax, Bx ;get available clusters in DX:AX
Mov Bx, Ax ;in DX:BX
Mov Ax, Dx
Mul Ax, Cx ;high word of bytes, if DX<>0 then error (too big)
Xchg Ax, Bx ;save in BX
Mul Ax, Cx ;low word of bytes
Add Dx, Bx ;add both high words, if carry then error (too big)
Mov [Bp+14], Ax ;save low word
Mov [Bp+12], Dx ;save high word
Clc
FreeDskDone
Pop Bp
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Ret
;--- invalid drive
FreeDskError
Mov Word [Bp+14], 0 ;save low word
Mov Word [Bp+12], 0 ;save high word
Stc
Jmps FreeDskDone
Endp ;Free_Dsk_P
;================================================
; Sound the speaker at a specified frequency for
; a specified amount of of time. The 16 bit
; frequency (in hertz -- minimum is 21) and the 16
; bit duration (in 1/100 seconds) must be passed
; on the stack. The duration is dependent upon the
; the speed and type of computer. If this routine
; is used on a faster computer, the number of nul
; loops executed for a single 1/100 second cycle
; should be adjusted accordingly. Though this
; routine directly manipulates the hardware, it
; does so in a fairly standardized manner, i.e.
; it should work on most compatibles.
Sound_Spk_P Proc Near
Push Ax
Push Cx
Push Dx
Push Bp
Mov Bp, Sp
Mov Al, 0B6h
Out 43h, Al ;timer mode
Mov Dx, 14h
Mov Ax, 4f38h ;divisor in DX.AX
Mov Cx, [Bp+12] ;tone
Cmp Cx, 15h ;check for minimum
Jae SoundSpkOk ;jump if ok
Mov Cx, 15h ;set to minimum (get divide overflow otherwise)
SoundSpkOk
Div Ax, Cx
Out 42h, Al ;timer 2 low byte
Mov Al, Ah
Out 42h, Al ;timer 2 high byte
In Al, 61h ;port B setting
Mov Ah, Al
Or Al, 3 ;turn on speaker
Out 61h, Al
Mov Dx, [Bp+10] ;duration
SoundSpkWait
Mov Cx, 2615 ;approx. 1/100 count (set for 4.77 MHz, 8088 computer)
SoundSpkLoop
Loop SoundSpkLoop ;loop for count
Dec Dx ;reduce count
Jnz SoundSpkWait ;loop back if more
Mov Al,Ah
Out 61h,Al ;turn off speaker
Pop Bp
Pop Dx
Pop Cx
Pop Ax
Ret 4
Endp
Db Neg $Chksum ;library checksum